﻿using System;
using System.Collections.Generic;
using System.Reflection;
using System.Runtime.Serialization;
using System.Text.RegularExpressions;

namespace HYCodeBase.ObjectPersistentSuit
{
	internal class UseBinder : SerializationBinder
	{
		static UseBinder()
		{
			UseBinder.m_lstAllAssembly = AssemblyUtility.GetAllAssembly(false);
		}

		internal UseBinder(Type input)
		{
			if (null != input)
			{
				if (!UseBinder.m_hashSetType.Contains(input))
				{
					this.AutoGetAttributeTypes(input);
					this.AutoSetTransformer(input);
					UseBinder.m_hashSetType.Add(input);
				}
				AssemblyUtility.GetAllInnerTypes(input, ref this.m_lstType, ref UseBinder.m_dicType);
			}
		}

		public override Type BindToType(string assemblyName, string typeName)
		{
			string key = assemblyName + typeName;
			Type type = null;
			Assembly assembly = null;
			if (UseBinder.m_dicType.TryGetValue(key, out type))
			{
				return type;
			}
			foreach (Assembly assembly2 in UseBinder.m_lstAllAssembly)
			{
				if (assembly2.GetName().FullName.Equals(assemblyName))
				{
					assembly = assembly2;
					break;
				}
			}
			if (null != assembly)
			{
				type = AssemblyUtility.TryGetType(typeName, assembly);
			}
			if (null == type)
			{
				foreach (Assembly oneAssembly in UseBinder.m_lstAllAssembly)
				{
					type = AssemblyUtility.TryGetType(typeName, oneAssembly);
					if (null != type)
					{
						break;
					}
				}
			}
			if (null == type)
			{
				foreach (Type type2 in this.m_lstType)
				{
					if (type2.FullName.Equals(typeName))
					{
						type = type2;
					}
				}
			}
			if (null == type)
			{
				type = this.GetGenericType(assemblyName, typeName);
			}
			if (null != type)
			{
				UseBinder.m_dicType.Add(key, type);
			}
			return type;
		}

		private Type GetGenericType(string assemblyName, string typeName)
		{
			Type result;
			try
			{
				if (!this.IfTypeNameIsGeneric(typeName))
				{
					result = null;
				}
				else
				{
					Type type = null;
					List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>();
					string typeName2;
					if (!this.TrySplitTypeStr(typeName, out typeName2, out list))
					{
						result = null;
					}
					else
					{
						type = this.BindToType(assemblyName, typeName2);
						if (null == type)
						{
							result = null;
						}
						else
						{
							List<Type> list2 = new List<Type>();
							foreach (KeyValuePair<string, string> keyValuePair in list)
							{
								Type type2 = this.BindToType(keyValuePair.Key, keyValuePair.Value);
								if (null == type2)
								{
									return null;
								}
								list2.Add(type2);
							}
							type = type.MakeGenericType(list2.ToArray());
							result = type;
						}
					}
				}
			}
			catch (Exception)
			{
				result = null;
			}
			return result;
		}

		private bool IfTypeNameIsGeneric(string inputTypeName)
		{
			return UseBinder.m_useGenericTagRegex.IsMatch(inputTypeName);
		}

		private bool TrySplitTypeStr(string inputTypeName, out string strGenericTypeName, out List<KeyValuePair<string, string>> parameterString)
		{
			strGenericTypeName = null;
			parameterString = new List<KeyValuePair<string, string>>();
			if (!UseBinder.m_useGenericTypePatternRegex.IsMatch(inputTypeName))
			{
				return false;
			}
			strGenericTypeName = UseBinder.m_useGenericTypePatternRegex.Match(inputTypeName).Value;
			List<string> list = new List<string>();
			if (UseBinder.m_useGenericGroupPatternRegex.IsMatch(inputTypeName))
			{
				string text = UseBinder.m_useGenericGroupPatternRegex.Match(inputTypeName).Value;
				text = this.ResetString(text);
				foreach (object obj in UseBinder.m_useGenericGroupPatternRegex.Matches(text))
				{
					Match match = (Match)obj;
					list.Add(this.ResetString(match.Value));
				}
				foreach (string input in list)
				{
					KeyValuePair<string, string> item;
					if (!this.GetParameterStringKVP(input, out item))
					{
						return false;
					}
					parameterString.Add(item);
				}
				return parameterString.Count != 0;
			}
			return false;
		}

		private bool GetParameterStringKVP(string input, out KeyValuePair<string, string> result)
		{
			result = default(KeyValuePair<string, string>);
			string[] array = input.Split(new char[]
			{
				','
			});
			if (array.Length < 5)
			{
				return false;
			}
			int num = array.Length - 4;
			string key = this.AppendString(array, num, array.Length);
			string value = this.AppendString(array, 0, num);
			result = new KeyValuePair<string, string>(key, value);
			return true;
		}

		private string AppendString(string[] splitResult, int useStartIndex, int useEndIndex)
		{
			string text = string.Empty;
			for (int i = useStartIndex; i < useEndIndex; i++)
			{
				text = this.AppendString(splitResult, text, i, useEndIndex - 1);
			}
			return this.TrimString(text);
		}

		private string AppendString(string[] splitResult, string inputString, int tempIndex, int useBoundary)
		{
			inputString += splitResult[tempIndex];
			if (tempIndex != useBoundary)
			{
				inputString += ",";
			}
			return inputString;
		}

		private string TrimString(string assemblyString)
		{
			assemblyString = assemblyString.Trim();
			assemblyString = assemblyString.Trim(new char[]
			{
				','
			});
			return assemblyString;
		}

		private string ResetString(string inputString)
		{
			inputString = inputString.Remove(0, 1);
			inputString = inputString.Remove(inputString.Length - 1, 1);
			return inputString;
		}

		private void AutoSetTransformer(Type inputOjbectType)
		{
			foreach (FieldInfo oneFieldInfo in inputOjbectType.GetRuntimeFields())
			{
				try
				{
					this.AdjuestField(oneFieldInfo);
				}
				catch (Exception)
				{
				}
			}
		}

		private void AdjuestField(FieldInfo oneFieldInfo)
		{
			if (!oneFieldInfo.FieldType.Name.Equals(UseBinder.m_NoneSerizeElementPackerType.Name) || !oneFieldInfo.FieldType.IsGenericType)
			{
				return;
			}
			Type type = oneFieldInfo.FieldType.GetGenericArguments()[0];
			Attribute customAttribute = oneFieldInfo.GetCustomAttribute(typeof(ObjectSerializeAttribute));
			if (customAttribute == null)
			{
				return;
			}
			ObjectSerializeAttribute objectSerializeAttribute = customAttribute as ObjectSerializeAttribute;
			if (objectSerializeAttribute.UseTransformer == null)
			{
				return;
			}
			Type type2 = UseBinder.m_useTransformerType.MakeGenericType(new Type[]
			{
				type
			});
			Type type3 = objectSerializeAttribute.UseTransformer.GetType();
			if (type2.IsAssignableFrom(type3))
			{
				Type type4 = UseBinder.m_NoneSerizeElementPackerType.MakeGenericType(new Type[]
				{
					type
				});
				type4.GetField("m_useType", BindingFlags.Static | BindingFlags.NonPublic).SetValue(null, type3);
				type4.GetField("m_useTransformer", BindingFlags.Static | BindingFlags.NonPublic).SetValue(null, objectSerializeAttribute.UseTransformer);
				return;
			}
		}

		private void AutoGetAttributeTypes(Type inputType)
		{
			try
			{
				Attribute customAttribute = inputType.GetCustomAttribute(typeof(ClassSerializeTypeAttribute));
				if (customAttribute != null)
				{
					ClassSerializeTypeAttribute classSerializeTypeAttribute = customAttribute as ClassSerializeTypeAttribute;
					if (classSerializeTypeAttribute != null)
					{
						Type[] thisTypes = classSerializeTypeAttribute.ThisTypes;
						if (thisTypes != null)
						{
							foreach (Type type in thisTypes)
							{
								if (!(null == type))
								{
									AssemblyUtility.GetAllInnerTypes(type, ref this.m_lstType, ref UseBinder.m_dicType);
								}
							}
						}
					}
				}
			}
			catch (Exception)
			{
			}
		}

		private const string m_strGenericTag = "`\\d+\\[";

		private const string m_strGenericGroupPattern = "\\[((?<Open>\\[)|(?<-Open>\\])|[^\\[\\]]+)*(?(Open)(?!))\\]";

		private const string m_strGenericTypePattern = "^.+?\\`\\d+";

		private const char m_splitTag = ',';

		private const int m_minSplitCount = 5;

		private const int m_nAssemblyCount = 4;

		private static Regex m_useGenericTagRegex = new Regex("`\\d+\\[");

		private static Regex m_useGenericGroupPatternRegex = new Regex("\\[((?<Open>\\[)|(?<-Open>\\])|[^\\[\\]]+)*(?(Open)(?!))\\]");

		private static Regex m_useGenericTypePatternRegex = new Regex("^.+?\\`\\d+");

		private static Type m_NoneSerizeElementPackerType = typeof(NoneSerizeElementPacker<>);

		private static Type m_useTransformerType = typeof(IClassInformationTransformer<>);

		private const string m_strNoneSerizeElementPackerTypeFiled = "m_useType";

		private const string m_strNoneSerizeElementPackerObjectFiled = "m_useTransformer";

		private static List<Assembly> m_lstAllAssembly = new List<Assembly>();

		private List<Type> m_lstType = new List<Type>();

		private static Dictionary<string, Type> m_dicType = new Dictionary<string, Type>();

		private static HashSet<Type> m_hashSetType = new HashSet<Type>();
	}
}
